/**
 * Agent Git操作工具类
 * 提供无交互的Git操作方法
 */

import { execSync } from 'child_process';
import { existsSync } from 'fs';
import {
  CommitMessageGenerator,
  commitMessages,
  type CommitMessageConfig,
} from './commit-message-generator.js';

export interface GitConfig {
  authorName: string;
  authorEmail: string;
  orgName: string;
  apiKey: string;
}

export interface GitOperationResult {
  success: boolean;
  message: string;
  error?: string;
}

export interface RepositoryInfo {
  url: string;
  gitUrl: string;
  branch: string;
  latestCommit?: string;
  status: 'clean' | 'dirty';
}

export class AgentGit {
  private config: GitConfig;

  constructor(config: GitConfig) {
    this.config = config;
    this.setupEnvironment();
  }

  /**
   * 设置Git环境变量避免交互
   */
  private setupEnvironment(): void {
    process.env.GIT_AUTHOR_NAME = this.config.authorName;
    process.env.GIT_AUTHOR_EMAIL = this.config.authorEmail;
    process.env.GIT_COMMITTER_NAME = this.config.authorName;
    process.env.GIT_COMMITTER_EMAIL = this.config.authorEmail;
    process.env.GIT_TERMINAL_PROMPT = '0';
    process.env.GIT_ASKPASS = 'echo';
  }

  /**
   * 安全执行Git命令
   */
  private execGitCommand(command: string): { stdout: string; success: boolean; error?: string } {
    try {
      const stdout = execSync(command, {
        encoding: 'utf8',
        stdio: ['pipe', 'pipe', 'pipe'],
        timeout: 30000, // 30秒超时
      });
      return { stdout: stdout.trim(), success: true };
    } catch (error: any) {
      return {
        stdout: '',
        success: false,
        error: error.message || 'Unknown error',
      };
    }
  }

  /**
   * 检查是否为Git仓库
   */
  isGitRepository(): boolean {
    return existsSync('.git');
  }

  /**
   * 初始化Git仓库
   */
  async initRepository(): Promise<GitOperationResult> {
    if (this.isGitRepository()) {
      return { success: true, message: 'Git repository already exists' };
    }

    const result = this.execGitCommand('git init --quiet');
    return {
      success: result.success,
      message: result.success ? 'Git repository initialized' : 'Failed to initialize repository',
      error: result.error,
    };
  }

  /**
   * 配置Git用户信息
   */
  async configureUser(): Promise<GitOperationResult> {
    const nameResult = this.execGitCommand(`git config user.name "${this.config.authorName}"`);
    const emailResult = this.execGitCommand(`git config user.email "${this.config.authorEmail}"`);

    if (nameResult.success && emailResult.success) {
      return { success: true, message: 'Git user configuration updated' };
    }

    return {
      success: false,
      message: 'Failed to configure Git user',
      error: nameResult.error || emailResult.error,
    };
  }

  /**
   * 添加所有文件到暂存区
   */
  async addAllFiles(): Promise<GitOperationResult> {
    const result = this.execGitCommand('git add . --all');
    return {
      success: result.success,
      message: result.success ? 'Files staged successfully' : 'Failed to stage files',
      error: result.error,
    };
  }

  /**
   * 检查是否有需要提交的更改
   */
  hasChangesToCommit(): boolean {
    const result = this.execGitCommand('git diff --cached --quiet');
    // diff --quiet 如果有差异会返回非零状态
    return !result.success;
  }

  /**
   * 提交更改
   */
  async commitChanges(message?: string): Promise<GitOperationResult> {
    if (!this.hasChangesToCommit()) {
      return { success: true, message: 'No changes to commit' };
    }

    const commitMessage =
      message ||
      commitMessages.automatedTask('自动化提交', [
        `代码更新 - ${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`,
        '自动添加所有文件变更',
        '标准化提交消息格式',
      ]);

    // 转义提交消息中的引号和特殊字符
    const escapedMessage = commitMessage.replace(/"/g, '\\"').replace(/\n/g, '\\n');
    const result = this.execGitCommand(`git commit -m "${escapedMessage}" --quiet`);

    return {
      success: result.success,
      message: result.success
        ? `Changes committed with standardized message`
        : 'Failed to commit changes',
      error: result.error,
    };
  }

  /**
   * 检查远程仓库是否存在
   */
  async checkRemoteRepository(repoUrl: string): Promise<boolean> {
    const result = this.execGitCommand(`git ls-remote "${repoUrl}"`);
    return result.success;
  }

  /**
   * 通过API创建远程仓库
   */
  async createRemoteRepository(repoName: string, description: string): Promise<GitOperationResult> {
    try {
      const response = await fetch(`https://gitee.com/api/v5/orgs/${this.config.orgName}/repos`, {
        method: 'POST',
        headers: {
          Authorization: `token ${this.config.apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: repoName,
          description: description,
          private: false,
          has_issues: true,
          has_wiki: true,
          auto_init: false,
        }),
      });

      const result: any = await response.json();

      if (response.ok && result.id) {
        return {
          success: true,
          message: `Remote repository '${repoName}' created successfully`,
        };
      } else {
        return {
          success: false,
          message: 'Failed to create remote repository',
          error: result?.message || 'API request failed',
        };
      }
    } catch (error: any) {
      return {
        success: false,
        message: 'Failed to create remote repository',
        error: error.message,
      };
    }
  }

  /**
   * 配置远程仓库
   */
  async configureRemote(repoUrl: string): Promise<GitOperationResult> {
    // 检查origin是否存在
    const checkResult = this.execGitCommand('git remote');
    const hasOrigin = checkResult.stdout.includes('origin');

    let result;
    if (hasOrigin) {
      result = this.execGitCommand(`git remote set-url origin "${repoUrl}"`);
    } else {
      result = this.execGitCommand(`git remote add origin "${repoUrl}"`);
    }

    return {
      success: result.success,
      message: result.success
        ? `Remote 'origin' ${hasOrigin ? 'updated' : 'added'}: ${repoUrl}`
        : 'Failed to configure remote',
      error: result.error,
    };
  }

  /**
   * 推送到远程仓库
   */
  async pushToRemote(): Promise<GitOperationResult> {
    // 先尝试正常推送
    let result = this.execGitCommand('git push --set-upstream origin main --quiet');

    if (!result.success) {
      // 如果失败，尝试强制推送
      result = this.execGitCommand(
        'git push --force-with-lease --set-upstream origin main --quiet'
      );
    }

    return {
      success: result.success,
      message: result.success ? 'Successfully pushed to remote' : 'Failed to push to remote',
      error: result.error,
    };
  }

  /**
   * 获取仓库信息
   */
  async getRepositoryInfo(): Promise<RepositoryInfo | null> {
    try {
      const branchResult = this.execGitCommand('git rev-parse --abbrev-ref HEAD');
      const remoteResult = this.execGitCommand('git remote get-url origin');
      const statusResult = this.execGitCommand('git status --porcelain');

      let latestCommit: string | undefined;
      const commitResult = this.execGitCommand('git log -1 --format="%h %s"');
      if (commitResult.success) {
        latestCommit = commitResult.stdout;
      }

      if (!branchResult.success || !remoteResult.success) {
        return null;
      }

      // 从Git URL提取Web URL
      const gitUrl = remoteResult.stdout;
      const webUrl = gitUrl.replace('.git', '').replace(':', '/').replace('git@', 'https://');

      return {
        url: webUrl,
        gitUrl: gitUrl,
        branch: branchResult.stdout,
        latestCommit,
        status: statusResult.stdout ? 'dirty' : 'clean',
      };
    } catch {
      return null;
    }
  }

  /**
   * 使用标准化提交消息提交更改
   */
  async commitWithStandardMessage(config: CommitMessageConfig): Promise<GitOperationResult> {
    if (!this.hasChangesToCommit()) {
      return { success: true, message: 'No changes to commit' };
    }

    const commitMessage = CommitMessageGenerator.generate(config);
    const escapedMessage = commitMessage.replace(/"/g, '\\"').replace(/\n/g, '\\n');
    const result = this.execGitCommand(`git commit -m "${escapedMessage}" --quiet`);

    return {
      success: result.success,
      message: result.success
        ? `Changes committed: ${config.type}(${config.scope || ''}): ${config.description}`
        : 'Failed to commit changes',
      error: result.error,
    };
  }

  /**
   * 完整的自动化工作流程
   */
  async automatedWorkflow(
    repoName: string,
    description: string,
    commitMessage?: string,
    commitConfig?: CommitMessageConfig
  ): Promise<GitOperationResult & { repositoryInfo?: RepositoryInfo }> {
    try {
      // 1. 初始化仓库
      const initResult = await this.initRepository();
      if (!initResult.success) return initResult;

      // 2. 配置用户
      const configResult = await this.configureUser();
      if (!configResult.success) return configResult;

      // 3. 添加文件
      const addResult = await this.addAllFiles();
      if (!addResult.success) return addResult;

      // 4. 提交更改
      let commitResult: GitOperationResult;
      if (commitConfig) {
        commitResult = await this.commitWithStandardMessage(commitConfig);
      } else {
        commitResult = await this.commitChanges(commitMessage);
      }
      if (!commitResult.success) return commitResult;

      // 5. 构建远程URL
      const repoUrl = `https://gitee.com/${this.config.orgName}/${repoName}.git`;

      // 6. 检查/创建远程仓库
      const repoExists = await this.checkRemoteRepository(repoUrl);
      if (!repoExists) {
        const createResult = await this.createRemoteRepository(repoName, description);
        if (!createResult.success) return createResult;
      }

      // 7. 配置远程
      const remoteResult = await this.configureRemote(repoUrl);
      if (!remoteResult.success) return remoteResult;

      // 8. 推送
      const pushResult = await this.pushToRemote();
      if (!pushResult.success) return pushResult;

      // 9. 获取仓库信息
      const repositoryInfo = await this.getRepositoryInfo();

      return {
        success: true,
        message: `Automated workflow completed successfully for ${repoName}`,
        repositoryInfo: repositoryInfo || undefined,
      };
    } catch (error: any) {
      return {
        success: false,
        message: 'Automated workflow failed',
        error: error.message,
      };
    }
  }
}

// 默认配置
export const createDefaultAgentGit = () => {
  return new AgentGit({
    authorName: 'Agent Auto Commit',
    authorEmail: 'agent@local.dev',
    orgName: 'ai-automate',
    apiKey: '5a95996937c2ae285fff63a418396f43',
  });
};
